from boot import (Union, QWidget, CurrentSelectedID, QFileDialog, IMG_ROOT_DIR, os, List, logger, BillType, BillCurrentFilter, GlobalWidget,
                  QApplication, QPixmap, QLineEdit)
from view.widget.qq9_messagebox import QQ9MessageBox, QQ9MessageBoxWidget, QQ9TipsMessageWidget
from view.pages.utils.message_box import message_box
from view.widget.qq9_page_base import QQ9PageBase
from view.com.bill_list_frame import BillListFrame
from view.com.bill_content_frame import BillContentFrame
from view.pages.utils.map import bill_content_dict_map
from view.pages.utils.db_d import db_cust_and_bill_wrapper, db_cust_wrapper
from db.db_customer import DBCustomer
from db.db_bill import DBBill
from view.widget.qq9_label import QQ9FromTitle
from view.widget.qq9_combobox import QQ9ComboBox
from view.widget.qq9_date_picker import QQ9DatePicker
from view.widget.qq9_line_edit import QQ9NumberLineEdit, QQ9LineEdit
from utils.qcodfe_ import generate_qrcode, delete_qrcode
from utils.id import generate_id
from view.widget.qq9_general_wrapper import popup
import hashlib


__all__ = ["PageBill"]


SHOW_BACK_NAME: bool = True
DELETE_RESULT: str = ""


class PageBill(QQ9PageBase):

    def __init__(self,
                    parent: Union[QWidget, None] = None,
                 ):
        super().__init__(parent)

        # 创建回款清单列表
        self.bill_list_frame = BillListFrame()
        self.main_h_layout.addWidget(self.bill_list_frame)

        # 创建回款内容框架
        self.bill_content_frame = BillContentFrame()
        self.main_h_layout.addWidget(self.bill_content_frame)

        # 初始化步骤
        # 1.刷新列表内容
        self.show_list_widget()
        # 2.绑定list_widget的点击事件(选择改变)
        self.bill_list_frame.list_widget.itemSelectionChanged.connect(self.show_content_widget)
        # 3.绑定编辑按钮信号
        self.bill_content_frame.edit_button.sgn_clicked.connect(self.set_bill_info)
        # 4.绑定删除按钮
        self.bill_content_frame.delete_button.sgn_clicked.connect(self.delete_bill_info)
        # 5.绑定新建按钮信号
        self.bill_list_frame.search_list_frame.add_button.sgn_clicked.connect(self.add_bill_info)
        # 6绑定筛选按钮信号
        self.bill_list_frame.search_list_frame.filter_button.sgn_clicked.connect(self.filter_bill_info)
        # 7绑定刷新按钮信号
        self.bill_list_frame.search_list_frame.refresh_button.sgn_clicked.connect(self.show_list_widget)
        # 8.绑定截屏按钮信号
        self.bill_list_frame.search_list_frame.screenshot_button.sgn_clicked.connect(self.screenshot)

    @bill_content_dict_map
    def show_list_widget(self, new_dict_list= None) -> None:
        # 1.刷新列表
        self.bill_list_frame.list_widget.refresh_list_widget(new_dict_list, show_back_name=SHOW_BACK_NAME)
        # 2.切换成LOGO
        self.bill_content_frame.set_no_content()

    @bill_content_dict_map
    def edit_list_widget(self, new_dict_list=None):
        # 编辑之后刷新列表
        self.bill_list_frame.list_widget.edit_list_widget(new_dict_list, show_back_name=SHOW_BACK_NAME)

    @bill_content_dict_map
    def delete_list_widget(self, new_dict_list=None):
        # 删除之后刷新列表
        self.bill_list_frame.list_widget.delete_list_widget(new_dict_list, show_back_name=SHOW_BACK_NAME)

    @bill_content_dict_map
    def add_list_widget(self, new_dict_list=None):
        # 添加之后刷新列表
        self.bill_list_frame.list_widget.add_list_widget(new_dict_list, show_back_name=SHOW_BACK_NAME)

    @db_cust_and_bill_wrapper
    def show_content_widget(self, cust_db: DBCustomer, bill_db: DBBill):
        # 刷新内容
        try:
            # 1.获取选中的Bill信息
            bill_info_dict = bill_db.get_info(CurrentSelectedID.bill_selected_id)
            # 2.获取cust信息
            cust_info_dict = cust_db.get_info(bill_info_dict["cust_id"])
            # 3.设置内容信息
            # 3.1 时间显示格式更改
            date_list = bill_info_dict["bill_datetime"].split("/")
            self.bill_content_frame.set_info(
                icon_path=cust_info_dict["cust_icon"],
                cust_name=cust_info_dict["cust_name"],
                bill_amount=bill_info_dict["bill_amount"],
                bill_id=bill_info_dict["bill_id"],
                bill_datetime=date_list[0] + "年" + date_list[1] + "月" + date_list[2] + "日",
                bill_type=bill_info_dict["bill_type"],
                remark=bill_info_dict["remark"],
                all_amount=self.amount_sum()
            )
            # 4.显示二维码
            self.bill_content_frame.qrcode_label.set_qrcode(IMG_ROOT_DIR + "/bill/" + bill_info_dict["bill_id"] + ".png")
            # 5.显示画面
            self.bill_content_frame.set_yes_content()
        except TypeError as te:
            self.show_list_widget()
            logger.warning(f"{te}由于删除了项目，本地获取item_id时不存在")

    @message_box(title="编辑回款信息", width=400, height=450)
    @db_cust_and_bill_wrapper
    def set_bill_info(self, w: QQ9MessageBox= None, cust_db: DBCustomer=None, bill_db: DBBill=None):
        GlobalWidget.root.showMaximized()
        # 编辑回款信息
        try:
            c = BillEditFrame(parent=w, add=False)
        except TypeError:
            logger.warning("没有选择用户，或用户不存在")
            # 2.切换成LOGO
            self.bill_content_frame.set_no_content()
            # 3.刷新列表
            self.delete_list_widget()
            return
        if w.exec():
            # 1.获取设置的客户ID
            cust_name = c.name_combobox.text()
            cust_id = cust_db.get_id_by_name(cust_name)
            # 2.获取设置的回款类型
            bill_type = c.type_combobox.text()
            # 3.获取设置的日期
            bill_datetime = c.datetime_picker.get_date()
            # 4.获取设置的金额
            bill_amount = c.amount_edit.text()
            # 5.获取设置的备注
            remark = c.remark_edit.text()
            # 6.写入数据库
            bill_db.update_bill_info(
                cust_id=cust_id,
                bill_datetime=bill_datetime,
                bill_type=bill_type,
                bill_amount=bill_amount,
                remark=remark,
                bill_id=CurrentSelectedID.bill_selected_id
            )
            # 7.更改二维码
            self._generate_qrcode(CurrentSelectedID.bill_selected_id, bill_amount)
            # 8.刷新列表
            self.edit_list_widget()

    @message_box(title="新建回款信息", width=400, height=450)
    @db_cust_and_bill_wrapper
    def add_bill_info(self, w: QQ9MessageBox= None, cust_db: DBCustomer=None, bill_db: DBBill=None):
        GlobalWidget.root.showMaximized()
        # 添加回款信息
        c = BillEditFrame(parent=w, add=True)
        if w.exec():
            # 1.获取设置的客户ID
            try:
                cust_name = c.name_combobox.text()
                cust_id = cust_db.get_id_by_name(cust_name)
            except TypeError:
                logger.warning("没有选择用户，或用户不存在")
                return
            # 2.获取设置的回款类型
            bill_type = c.type_combobox.text()
            # 3.获取设置的日期
            bill_datetime = c.datetime_picker.get_date()
            # 4.获取设置的金额
            bill_amount = c.amount_edit.text()
            # 5.获取设置的备注
            remark = c.remark_edit.text()
            # 6.生成bill_id
            bill_id = generate_id("20000")
            # 7.写入数据库
            bill_db.add_info(
                bill_id=bill_id,
                cust_id=cust_id,
                bill_datetime=bill_datetime,
                bill_type=bill_type,
                bill_amount=bill_amount,
                remark=remark,
            )
            # 8.更改当前选中ID
            CurrentSelectedID.bill_selected_id = bill_id
            # 9.生成二维码
            self._generate_qrcode(bill_id, bill_amount)
            # 10.刷新列表
            self.add_list_widget()

    @message_box(title="删除回款信息", width=300, height=150)
    @db_cust_and_bill_wrapper
    def delete_bill_info(self, w: QQ9MessageBox= None, cust_db: DBCustomer=None, bill_db: DBBill=None):
        # 删除回款信息
        QQ9TipsMessageWidget(parent=w, text="确定删除此回款单吗？")
        if w.exec():
            # 1.删除客户信息密码确认
            self.delete_bill_info_configuration()


    @message_box(title="删除回款单密码确认", width=400, height=150)
    @db_cust_and_bill_wrapper
    def delete_bill_info_configuration(self, w: QQ9MessageBox= None, cust_db: DBCustomer=None, bill_db: DBBill=None):
        # 删除客户信息密码确认
        global DELETE_RESULT
        c = PasswordEditFrame(parent=w)
        if w.exec():
            # 哈希256加密密码
            hash_object = hashlib.sha256(c.password_edit.text().encode())
            hex_dig = hash_object.hexdigest()
            if hex_dig == "c67ea1a7c60a833a8b56a9e2b99d8e4803b4d3dcb7dc5982313a51ab264ee15b":
                # 1.在数据库中删除
                bill_db.delete_info(CurrentSelectedID.bill_selected_id)
                # 2.切换成LOGO
                self.bill_content_frame.set_no_content()
                # 3删除二维码
                self._delete_qrcode(CurrentSelectedID.bill_selected_id)
                # 4.刷新列表
                self.delete_list_widget()
                DELETE_RESULT = "删除成功"
            else:
                DELETE_RESULT = "密码错误，删除失败"
            self.delete_finish_tips()

    @message_box(title="删除结果", width=300, height=150)
    def delete_finish_tips(self, w: QQ9MessageBox=None):
        # 删除结果信息
        global DELETE_RESULT
        QQ9TipsMessageWidget(parent=w, text=DELETE_RESULT)
        if w.exec():
            pass

    @message_box(title="选择筛选按条件", width=400, height=170)
    @db_cust_and_bill_wrapper
    def filter_bill_info(self, w: QQ9MessageBox= None, cust_db: DBCustomer=None, bill_db: DBBill=None):
        # 更改过滤条件
        c = FilterFrame(parent=w)
        if w.exec():
            # 1.更改筛选条件
            cust_name = c.name_combobox.text()
            if cust_name == "全部":
                BillCurrentFilter.cust_id = "*"
            else:
                BillCurrentFilter.cust_id = cust_db.get_id_by_name(cust_name)
            # 2.刷新列表
            self.show_list_widget()
            # 3.切换成LOGO
            self.bill_content_frame.set_no_content()

    @popup
    def screenshot(self):
        try:
            # 截图
            width, height = GlobalWidget.root.width(), GlobalWidget.root.height()
            GlobalWidget.root.resize(881, 1000)
            pixmap = self.bill_content_frame.grab()
            GlobalWidget.root.resize(width, height)
            pixmap.save(IMG_ROOT_DIR + "/screenshot/" + "刚刚的账单截图" + ".png", "PNG", quality=100)

            # os.startfile(IMG_ROOT_DIR + "/screenshot/")

            # 自动放入粘贴板
            img = QPixmap(IMG_ROOT_DIR + "/screenshot/" + "刚刚的账单截图" + ".png")
            clipboard = QApplication.clipboard()
            clipboard.setPixmap(img)
            return "账单截图已经复制入粘贴板", True
        except Exception as e:
            logger.error(e)
            return "截图失败", False


    @db_cust_and_bill_wrapper
    def amount_sum(self, cust_db: DBCustomer=None, bill_db: DBBill=None) -> str:
        # 获取当前选中的cust_id
        # 1.获取设置的客户ID
        bill_id = CurrentSelectedID.bill_selected_id
        cust_id = bill_db.get_info(bill_id= bill_id)["cust_id"]
        # 2.获取该客户所有信息
        bill_info_by_cust = bill_db.get_all_info_by_cust(cust_id=cust_id)
        # 3.合计金额
        sum_amount = str(sum([int(i["bill_amount"]) for i in bill_info_by_cust if i != ""]))
        return sum_amount


    @staticmethod
    def _generate_qrcode(bill_id: str, bill_amount: str):
        content = "ID:" + bill_id + ";" + "AMOUNT:" + bill_amount + ";"
        generate_qrcode(code=content, img_path=IMG_ROOT_DIR + "/bill/" + bill_id + ".png")

    @staticmethod
    def _delete_qrcode(bill_id: str):
        delete_qrcode(img_path=IMG_ROOT_DIR + "/bill/" + bill_id + ".png")


class BillEditFrame(QQ9MessageBoxWidget):

    @db_cust_wrapper
    def __init__(self,
                 parent: Union[QWidget, None] = None,
                 add: bool = False,
                 cust_db: DBCustomer = None
                 ):
        super().__init__(parent, add)

        # 标题
        self.name_label = QQ9FromTitle(text="客户姓名")
        self.type_label = QQ9FromTitle(text="回款方式")
        self.datetime_label = QQ9FromTitle(text="回款时间")
        self.amount_label = QQ9FromTitle(text="回款金额")
        self.remark_label = QQ9FromTitle(text="备注")

        # 客户姓名
        self.name_combobox = QQ9ComboBox()
        self.name_combobox.addItems([i["cust_name"] for i in cust_db.get_all_info()])

        # 回款方式
        self.type_combobox = QQ9ComboBox()
        self.type_combobox.addItems(BillType.type_list)

        # 回款时间
        self.datetime_picker = QQ9DatePicker()
        self.datetime_picker.set_current_date()

        # 回款金额
        self.amount_edit = QQ9NumberLineEdit()

        # 备注
        self.remark_edit = QQ9LineEdit()

        self.main_g_layout.addWidget(self.name_label, 0, 0)
        self.main_g_layout.addWidget(self.name_combobox, 0, 1)
        self.main_g_layout.addWidget(self.type_label, 1, 0)
        self.main_g_layout.addWidget(self.type_combobox, 1, 1)
        self.main_g_layout.addWidget(self.datetime_label, 2, 0)
        self.main_g_layout.addWidget(self.datetime_picker, 2, 1)
        self.main_g_layout.addWidget(self.amount_label, 3, 0)
        self.main_g_layout.addWidget(self.amount_edit, 3, 1)
        self.main_g_layout.addWidget(self.remark_label, 4, 0)
        self.main_g_layout.addWidget(self.remark_edit, 4, 1)

        if not add:
            self.set_info()

    @db_cust_and_bill_wrapper
    def set_info(self, cust_db: DBCustomer=None, bill_db: DBBill=None):
        # 1.获取客户姓名
        self.name_combobox.setCurrentText(cust_db.get_name_by_id(bill_db.get_info(CurrentSelectedID.bill_selected_id)["cust_id"]))
        # 2.获取回款方式
        self.type_combobox.setCurrentText(bill_db.get_info(CurrentSelectedID.bill_selected_id)["bill_type"])
        # 3.获取回款时间
        self.datetime_picker.set_date(bill_db.get_info(CurrentSelectedID.bill_selected_id)["bill_datetime"])
        # 4.获取回款金额
        self.amount_edit.setText(bill_db.get_info(CurrentSelectedID.bill_selected_id)["bill_amount"])
        # 5.获取备注
        self.remark_edit.setText(bill_db.get_info(CurrentSelectedID.bill_selected_id)["remark"])


class FilterFrame(QQ9MessageBoxWidget):

    @db_cust_wrapper
    def __init__(self,
                 parent: Union[QWidget, None] = None,
                 cust_db: DBCustomer = None
                 ):
        super().__init__(parent=parent)

        self.name_label = QQ9FromTitle(text="客户姓名")

        # 客户姓名
        self.name_combobox = QQ9ComboBox()
        self.name_combobox.addItems(["全部"] + [i["cust_name"] for i in cust_db.get_all_info()])

        self.main_g_layout.addWidget(self.name_label, 0, 0)
        self.main_g_layout.addWidget(self.name_combobox, 0, 1)


class PasswordEditFrame(QQ9MessageBoxWidget):

    def __init__(self,
                 parent: Union[QWidget, None] = None,
                 ):
        super().__init__(parent)

        # 标题
        self.name_label = QQ9FromTitle(text="删除密码")

        # 密码框
        self.password_edit = QQ9LineEdit()
        self.password_edit.setEchoMode(QLineEdit.Password)

        self.main_g_layout.addWidget(self.name_label, 0, 0)
        self.main_g_layout.addWidget(self.password_edit, 0, 1)

